#ifndef GAMEENGINE_CORE_GRAPH_H
#define GAMEENGINE_CORE_GRAPH_H

#include <GameEngine/Core/core_settings.h>

#include <set>
#include <QtCore/QMap>

#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

//! Class in charge of representing a graph
/*!
 *  A graph is made of nodes and links between nodes
 *
 @todo Setup unit tests
 */
template <class N, class L>
class Graph {

public:
	//! Typedef to handle node pointers
	typedef N* N_pointer;
	//! Typedef to handle constant node pointers
	typedef const N* N_pointer_const;
	//! Typedef to handle link pointers
	typedef L* L_pointer;
	//! Typedef to handle constant link pointers
	typedef const L* L_pointer_const;
	//! Typedef to handle a set of link pointers
	typedef std::set<L_pointer> LinkSet;

public:
	Graph();
	Graph(const Graph& rhs);
	~Graph();
	Graph& operator=(const Graph& rhs);

	const std::set< N >& nodes() const;
	const std::set< L >& links() const;
	const LinkSet& links(N_pointer_const node) const;

	N_pointer add_node(const N& node);
	N_pointer find_node(const N& node);
	N_pointer_const find_node(const N& node) const;
	bool remove_node(const N& node, bool remove_links = true);

	L_pointer add_link(const L& link);
	L_pointer find_link(const L& link);
	L_pointer_const find_link(const L& link) const;
	bool remove_link(const L& link);
	bool remove_links(const N& node);

protected:
	//! The set of nodes associated to the graph
	std::set< N > nodes_;
	//! The set of node links associated to the graph
	std::set< L > links_;

	//! Map nodes to their associated links
	QMap< N_pointer_const, LinkSet > map_;

	//! Default link
	static LinkSet no_links_;
};

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Core/Graph/graph.hpp>

#endif
